home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 3006 / 3006.xpi / components / dhNetworkProbe.js < prev    next >
Text File  |  2010-01-15  |  16KB  |  514 lines

  1. /******************************************************************************
  2.  *            Copyright (c) 2006-2009 Michel Gutierrez. All Rights Reserved.
  3.  ******************************************************************************/
  4.  
  5. /**
  6.  * Constants.
  7.  */
  8.  
  9. const NS_NWPROBE_CID = Components.ID("{29eb6720-7684-4b04-bc58-c18f554c6d55}");
  10. const NS_NWPROBE_PROG_ID = "@downloadhelper.net/network-probe;1";
  11. const DHNS = "http://downloadhelper.net/1.0#";
  12.  
  13. var Util=null;
  14.  
  15. /**
  16. * Object constructor
  17. */
  18. function NetProbe() {
  19.     try {
  20.         //dump("[NetProbe] constructor\n");
  21.         var prefService=Components.classes["@mozilla.org/preferences-service;1"]
  22.                                            .getService(Components.interfaces.nsIPrefService);
  23.         this.pref=prefService.getBranch("dwhelper.");
  24.         
  25.         this.entries={};
  26.         this.updateDone=false;
  27.         this.prefBranch2=this.pref.QueryInterface(Components.interfaces.nsIPrefBranch2);
  28.         this.prefBranch2.addObserver("", this, false);
  29.         this.updateReqExtensions();
  30.         this.updateMediaWeight();
  31.         this.typePattern=new RegExp("^(audio|video)/");
  32.         this.ytSigPattern=/^(http:\/\/(?:[^\/]*youtube\..*|.*origin=[^\/&]*youtube\..*))(?:&|&)signature.*(?:&|&)ip=.*$/;
  33.         this.listMgr=Components.classes["@downloadhelper.net/media-list-manager"]
  34.                                         .getService(Components.interfaces.dhIMediaListMgr);
  35.  
  36.         this.cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
  37.                                                .getService(Components.interfaces.nsICacheService);
  38.         this.httpCacheSession = this.cacheService.createSession("HTTP", 
  39.             Components.interfaces.nsICache.STORE_ANYWHERE,
  40.             Components.interfaces.nsICache.STREAM_BASED);
  41.         this.httpCacheSession.doomEntriesIfExpired=false;
  42.         this.core=Components.classes["@downloadhelper.net/core;1"].
  43.             getService(Components.interfaces.dhICore);
  44.         this.core.registerProbe(this);
  45.     } catch(e) {
  46.         dump("[NetProbe] !!! constructor: "+e+"\n");
  47.     }
  48. }
  49.  
  50. NetProbe.prototype = {}
  51.  
  52. NetProbe.prototype.handleDocument=function(document,window) {
  53. }
  54.  
  55. NetProbe.prototype.handleRequest=function(request) {
  56.     //dump("[NetProbe] handleRequest("+request.name+")\n");
  57.     var url=request.name;
  58.     try {
  59.         var cacheTracker=true;
  60.         try {
  61.             cacheTracker=this.pref.getBoolPref("cache-tracker");
  62.         } catch(e) {}
  63.         if(cacheTracker) {
  64.  
  65.             var httpChannel=request.QueryInterface(Components.interfaces.nsIHttpChannel);
  66.             var wnd=null;
  67.             if(httpChannel.notificationCallbacks) {
  68.                 try {
  69.                     var notif=httpChannel.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  70.                     wnd=notif.getInterface(Components.interfaces.nsIDOMWindow);
  71.                 } catch(e) { }
  72.             }
  73.             if(wnd==null && httpChannel.loadGroup && httpChannel.loadGroup.notificationCallbacks) {
  74.                 try {
  75.                     var lgNotif=httpChannel.loadGroup.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  76.                     wnd=lgNotif.getInterface(Components.interfaces.nsIDOMWindow);
  77.                 } catch(e) {}
  78.             }
  79.  
  80.             /*
  81.             function checkCacheTracker(url,mediaresp,wnd) {
  82.                 mediaresp.checkCacheTracker(url,wnd);            
  83.             }
  84.             setTimeout(checkCacheTracker,0,url,this,wnd);
  85.             */
  86.             this.checkCacheTracker(url,wnd);
  87.         }
  88.             
  89.     } catch(e) { 
  90.         dump("!!! [NetProbe] handleRequest("+request.name+"): "+e+"\n");        
  91.     }
  92.  
  93. }
  94.  
  95. NetProbe.prototype.handleResponse=function(request) {
  96.     try {
  97.         
  98.         //dump("[NetProbe] handleResponse("+request.name+")\n");
  99.     
  100.         var murl=request.name;
  101.         var httpChannel=request.QueryInterface(Components.interfaces.nsIHttpChannel);
  102.         
  103.         var location=null;
  104.         try {
  105.             location=httpChannel.getResponseHeader("location");
  106.         } catch(e) {}
  107.         if(location) {
  108.             if(this.entries[murl]) {
  109.                 delete this.entries[murl];
  110.             }
  111.             return;
  112.         }
  113.         
  114.         var contentType=null;
  115.         try {
  116.             contentType=httpChannel.getResponseHeader("content-type");
  117.         } catch(e) {}
  118.         var contentLength=null;
  119.         try {
  120.             contentLength=httpChannel.getResponseHeader("content-length");
  121.         } catch(e) {}
  122.         var contentDisp=null;
  123.         try {
  124.             contentDisp=httpChannel.getResponseHeader("content-disposition");
  125.         } catch(e) {}
  126.         
  127.         if(contentLength!=null) {
  128.         
  129.             var tms="100";
  130.             try {
  131.                 tms=this.pref.getCharPref("trigger-min-size");
  132.             } catch(e) {}
  133.             tms=parseFloat(tms);
  134.             if(!isNaN(tms)) {
  135.                 if(contentLength<tms*1024)
  136.                     return;
  137.             }
  138.         }
  139.     
  140.         var wnd=null;
  141.         if(httpChannel.loadGroup && httpChannel.loadGroup.notificationCallbacks) {
  142.             try {
  143.                 var lgNotif=httpChannel.loadGroup.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  144.                 wnd=lgNotif.getInterface(Components.interfaces.nsIDOMWindow);
  145.             } catch(e) {}
  146.         }
  147.         if(wnd==null && httpChannel.notificationCallbacks) {
  148.             try {
  149.                 var notif=httpChannel.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  150.                 wnd=notif.getInterface(Components.interfaces.nsIDOMWindow);
  151.             } catch(e) {}
  152.         }
  153.     
  154.         var filename=this.analyzeMeta(murl,contentType,contentDisp,contentLength,wnd);
  155.         if(filename!=null) {
  156.     
  157.             var forceCaching=true;
  158.             try {
  159.                 forceCaching=this.pref.getBoolPref("force-cache");
  160.             } catch(e) {}
  161.             
  162.             if(forceCaching) {
  163.                 httpChannel.setResponseHeader("Cache-Control","max-age="+24*60*60,false);
  164.             }
  165.  
  166. /*
  167.             var referer=null;
  168.             try {
  169.                 referer=request.getRequestHeader("referer");
  170.             } catch(e) {
  171.             }
  172. */
  173.         }
  174.     } catch(e) {
  175.         dump("!!! [NetProbe] handleResponse("+request.name+"): "+e+"\n");
  176.     }
  177. }
  178.  
  179. NetProbe.prototype.checkCacheTracker=function(url,wnd) {
  180.     try {
  181.         var cacheEntryDescriptor=this.httpCacheSession.openCacheEntry(url, 
  182.                     Components.interfaces.nsICache.ACCESS_READ, false);
  183.         if(cacheEntryDescriptor && (cacheEntryDescriptor.accessGranted & 1)) {            
  184.                 var headers=cacheEntryDescriptor.getMetaDataElement("response-head");
  185.                 if(/Location:/i.test(headers)) {
  186.                     cacheEntryDescriptor.close();
  187.                     return;
  188.                 }
  189.     
  190.                 var contentType=null;
  191.                 try {
  192.                     contentType=/Content-Type: *(.*)/i.exec(headers)[1];
  193.                 } catch(e) {}
  194.                 var contentLength=null;
  195.                 try {
  196.                     contentLength=/Content-Length: *(.*)/i.exec(headers)[1];
  197.                 } catch(e) {}
  198.                 var contentDisp=null;
  199.                 try {
  200.                     contentDisp=/Content-Disposition: *(.*)/i.exec(headers)[1];
  201.                 } catch(e) {}
  202.                 
  203.                 var fn=this.analyzeMeta(url,contentType,contentDisp,contentLength,wnd);
  204.                 if(fn!=null) {
  205.                     //dump("[MediaResp] checkCacheTracker("+url+"): hit\n");
  206.                 }
  207.                 cacheEntryDescriptor.close();
  208.             }
  209.     } catch(e) {
  210.         //dump("!!! [NetProbe] checkCacheTracker(): "+e+"\n");
  211.     }        
  212. }
  213.  
  214. NetProbe.prototype.analyzeMeta = function(murl,contentType,contentDisp,contentLength,wnd) {
  215.     var hit=false;
  216.     var filename=null;
  217.   
  218.     if(contentType!=null && this.typePattern.test(contentType)) {
  219.         var excludeAsf=true;
  220.         try {
  221.             excludeAsf=this.pref.getBoolPref("exclude-ms-asf");
  222.         } catch(e) {}
  223.         if(excludeAsf) {
  224.             if(!/ms-asf$/.test(contentType))
  225.                 hit=true;
  226.         } else {
  227.             hit=true;
  228.         }
  229.     }
  230.     
  231.     if(!hit) {
  232.         if(this.reqPattern.test(murl)) {
  233.             hit=true;
  234.         }
  235.     }
  236.     
  237.     if(hit==false && this.mediaWeightEnabled==true) {
  238.         try {
  239.             if(contentLength!=null && isNaN(contentLength)==false && contentLength>=this.mediaWeightThreshold) {
  240.                 hit=true;
  241.             }    
  242.         } catch(e) {
  243.         }
  244.     }
  245.  
  246.     if(hit) {
  247.     
  248.         var extra={};
  249.         filename=this.guessFileName(murl,contentType,contentDisp,wnd,extra);
  250.     
  251.         try {
  252.     
  253.             if(filename.length>64) {
  254.                 var parts=/^(.*)(\..*?)$/.exec(filename);
  255.                 filename=parts[1].substr(0,64-parts[2].length)+parts[2];
  256.             }
  257.     
  258.             this.entries[murl]={
  259.                 url: murl, filename: filename,
  260.                 time: new Date().getTime()
  261.                 };
  262.     
  263.             var pageUrl=null;
  264.             if(wnd!=null && wnd.document) {
  265.                 this.entries[murl].pageUrl=wnd.document.URL;
  266.                 pageUrl=wnd.document.URL;
  267.             }
  268.             
  269.             var desc=Components.classes["@mozilla.org/properties;1"].
  270.                 createInstance(Components.interfaces.nsIProperties);
  271.             Util.setPropsString(desc,"media-url",murl);
  272.             Util.setPropsString(desc,"file-extension",extra.extension);
  273.             Util.setPropsString(desc,"file-name",filename.replace(/[^a-zA-Z0-9\.\- ]/g,"_"));
  274.             Util.setPropsString(desc,"label",filename);
  275.             Util.setPropsString(desc,"page-url",pageUrl);
  276.             Util.setPropsString(desc,"icon-url","chrome://dwhelper/skin/mediaresp.gif");
  277.             Util.setPropsString(desc,"capture-method","network");
  278.     
  279.             if(wnd && wnd.document)
  280.                 desc.set("window-document",wnd);
  281.             this.core.addEntry(desc);
  282.     
  283.             try {
  284.                 if(/\..{3}$/.test(filename)) {
  285.                     var extension=/\.(.{3})$/.exec(filename)[1];
  286.                     
  287.                     if(extension=="flv" || extension=="mp4") {
  288.                         var wnd=null;
  289.                         try {
  290.                             wnd=httpChannel.notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow);
  291.                         } catch(e) {
  292.                         }
  293.                         var url=null;
  294.                         if(wnd!=null && wnd.document!=null)
  295.                             url=wnd.document.URL;
  296.                         if(!/^http:\/\/[^\/]*downloadhelper.net\/watch\.php/.test(murl)) {
  297.                             this.listMgr.addToList("http://downloadhelper.net/1.0#history-list",
  298.                                     Util.getPropsString(desc,"media-url"),
  299.                                     Util.getPropsString(desc,"file-extension"),
  300.                                     Util.getPropsString(desc,"page-url"),
  301.                                     Util.getPropsString(desc,"file-name"),
  302.                                     Util.getPropsString(desc,"page-url"));
  303.                         }
  304.                     }
  305.                 }
  306.             } catch(e) {
  307.             }
  308.             
  309.         
  310.         } catch(e) {
  311.             dump("!!! [NetProbe] analyzeMeta: "+e+"\n");
  312.         }
  313.  
  314.         return filename;
  315.     }
  316.     return null;
  317. }
  318.  
  319. NetProbe.prototype.updateReqExtensions=function() {
  320.     var exts="flv|ram|mpg|mpeg|avi|rm|wmv|mov|asf|mp3|rar|movie|divx";
  321.     try {
  322.         exts=this.pref.getCharPref("mediareq-extensions");
  323.     } catch(e) {
  324.     }
  325.     this.reqPattern=new RegExp("[/\\?&]([^/\\?&=]+\\.("+exts+"))(?:$|\\?|&|/)");
  326. }
  327.  
  328. NetProbe.prototype.updateMediaWeight=function() {
  329.     var mediaWeight=""
  330.     try {
  331.         mediaWeight=this.pref.getCharPref("mediaweight");
  332.     } catch(e) {}
  333.     if(mediaWeight.length==0 || isNaN(parseInt(mediaWeight))) {
  334.         this.mediaWeightEnabled=false;        
  335.     } else {
  336.         this.mediaWeightEnabled=true;        
  337.         this.mediaWeightThreshold=parseInt(mediaWeight)*1024;
  338.     }
  339. }
  340.  
  341. NetProbe.prototype.observe=function(subject,topic,data) {
  342.     if(topic=="nsPref:changed") {
  343.         if(data=="mediareq-extensions")
  344.             this.updateReqExtensions();
  345.         if(data=="mediaweight")
  346.             this.updateMediaWeight();
  347.     }
  348. }
  349.  
  350. NetProbe.prototype.guessFileName=function(murl,contentType,contentDisp,wnd,extra) {
  351.     var filename=null;
  352.     var extension=null;
  353.     if(contentDisp!=null) {
  354.         if(/filename=/.test(contentDisp)) {
  355.             filename=/filename="?([^;"]*)/.exec(contentDisp)[1];
  356.             try {
  357.                 extension=/.*\.(.*?)$/.exec(filename)[1];
  358.             } catch(e) {
  359.                 extension="";
  360.             }
  361.         }
  362.     }
  363.     if(filename==null) {
  364.         if(contentType!=null && /^video\/x-.*$/.test(contentType)) {
  365.             extension=/video\/x-([^;]*)/.exec(contentType)[1];
  366.         } else if(contentType!=null && /^video\/.+$/.test(contentType)) {
  367.             extension=/video\/([^ ,]*).*$/.exec(contentType)[1];
  368.         } else if(contentType!=null && /^audio\/.+$/.test(contentType)) {
  369.             extension=/audio\/(?:x-)?([^ ,]*).*?$/.exec(contentType)[1];
  370.         } else {
  371.             if(/^[^\?]*\.[0-9a-zA-Z]{1,5}$/.test(murl))
  372.                 extension=/\.([0-9a-zA-Z]{1,5})$/.exec(murl)[1];
  373.             else
  374.                 extension="flv";
  375.         }
  376.         var re=new RegExp("([^/&\\?]+\\."+extension+")(?:$|&|\\?)");
  377.         if(re.test(murl)) {
  378.             var m=re.exec(murl);
  379.             filename=m[1];
  380.         } else if(this.reqPattern.test(murl)) {
  381.             var m=this.reqPattern.exec(murl);
  382.             filename=m[1];
  383.             extension=m[2];
  384.         } else {
  385.             try {
  386.                 var title=null;
  387.                 if(wnd) {
  388.                     title=Util.xpGetString(wnd.document.documentElement,
  389.                         "/html/head/meta[@name='title']/@content");
  390.                     if(title==null || title=="")
  391.                         title=Util.xpGetString(wnd.document.documentElement,
  392.                             "/html/head/title");
  393.                 }
  394.                 if(title==null || title=="")
  395.                     title="file-"+Math.floor(Math.random()*1000000000);
  396.                 filename=title.replace(/[^a-zA-Z0-9-]+/g,"_")+"."+extension;
  397.             } catch(e) {
  398.                 filename="file-"+Math.floor(Math.random()*1000000000)+"."+extension;
  399.             }
  400.         }
  401.     }
  402.     extra.extension=extension;
  403.     return filename;
  404. }
  405.  
  406. NetProbe.prototype.observe=function(subject,topic,data) {
  407.     //dump("[NetProbe] observe("+subject+","+topic+","+data+")\n");
  408.     if(topic=="quit-application") {
  409.         this.prefBranch2.removeObserver("",this);
  410.         this.observerService.removeObserver(this,"quit-application");
  411.     }
  412. }
  413.  
  414. NetProbe.prototype.QueryInterface = function(iid) {
  415.     //dump("[NetProbe] QueryInterface("+iid+")\n");
  416.     if(
  417.             iid.equals(Components.interfaces.dhIProbe) ||
  418.             iid.equals(Components.interfaces.nsIObserver) ||
  419.         iid.equals(Components.interfaces.nsISupports)
  420.     ) {
  421.         return this;
  422.     }
  423.     throw Components.results.NS_ERROR_NO_INTERFACE;
  424. }
  425.  
  426. var vNetProbeModule = {
  427.     firstTime: true,
  428.     
  429.     /*
  430.      * RegisterSelf is called at registration time (component installation
  431.      * or the only-until-release startup autoregistration) and is responsible
  432.      * for notifying the component manager of all components implemented in
  433.      * this module.  The fileSpec, location and type parameters are mostly
  434.      * opaque, and should be passed on to the registerComponent call
  435.      * unmolested.
  436.      */
  437.     registerSelf: function (compMgr, fileSpec, location, type) {
  438.  
  439.         if (this.firstTime) {
  440.             this.firstTime = false;
  441.             throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  442.         }
  443.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  444.         compMgr.registerFactoryLocation(NS_NWPROBE_CID,
  445.                                         "NetProbe",
  446.                                         NS_NWPROBE_PROG_ID, 
  447.                                         fileSpec,
  448.                                         location,
  449.                                         type);
  450.     },
  451.  
  452.     unregisterSelf: function(compMgr, fileSpec, location) {
  453.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  454.         compMgr.unregisterFactoryLocation(NS_DH_NWPROBE_CID, fileSpec);
  455.     },
  456.  
  457.     /*
  458.      * The GetClassObject method is responsible for producing Factory and
  459.      * SingletonFactory objects (the latter are specialized for services).
  460.      */
  461.     getClassObject: function (compMgr, cid, iid) {
  462.         if (!cid.equals(NS_NWPROBE_CID)) {
  463.             throw Components.results.NS_ERROR_NO_INTERFACE;
  464.         }
  465.  
  466.         if (!iid.equals(Components.interfaces.nsIFactory)) {
  467.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  468.         }
  469.  
  470.         return this.vNetProbeFactory;
  471.     },
  472.  
  473.     /* factory object */
  474.     vNetProbeFactory: {
  475.         /*
  476.          * Construct an instance of the interface specified by iid, possibly
  477.          * aggregating it with the provided outer.  (If you don't know what
  478.          * aggregation is all about, you don't need to.  It reduces even the
  479.          * mightiest of XPCOM warriors to snivelling cowards.)
  480.          */
  481.         createInstance: function (outer, iid) {
  482.             if (outer != null) {
  483.                 throw Components.results.NS_ERROR_NO_AGGREGATION;
  484.             }
  485.     
  486.             if(Util==null) 
  487.                 Util=Components.classes["@downloadhelper.net/util-service;1"]
  488.                     .getService(Components.interfaces.dhIUtilService);
  489.  
  490.             return new NetProbe().QueryInterface(iid);
  491.         }
  492.     },
  493.  
  494.     /*
  495.      * The canUnload method signals that the component is about to be unloaded.
  496.      * C++ components can return false to indicate that they don't wish to be
  497.      * unloaded, but the return value from JS components' canUnload is ignored:
  498.      * mark-and-sweep will keep everything around until it's no longer in use,
  499.      * making unconditional ``unload'' safe.
  500.      *
  501.      * You still need to provide a (likely useless) canUnload method, though:
  502.      * it's part of the nsIModule interface contract, and the JS loader _will_
  503.      * call it.
  504.      */
  505.     canUnload: function(compMgr) {
  506.         return true;
  507.     }
  508. };
  509.  
  510. function NSGetModule(compMgr, fileSpec) {
  511.     return vNetProbeModule;
  512. }
  513.  
  514.